<?php
/**
 * @author tuanla
 *
 */

class UserController extends Controller
{
	/**
	 * actionShow
	 *
	 * Get overall information about authenticated user or other user via user id
	 *
	 * @param user_id:	If this param not passing,　the id of the authenticated user as default value.
	 * 
	 * @return array of user information such as user id, username, fullname, avatar, location,
	 * website, biography, number of tweet, number of following, number of follower
	 */
	public function actionShow()
	{
		$login_id = Yii::app()->user->id;
		$user_id = Yii::app()->request->getParam('user_id', $login_id);
		$follow_status = 0;
		
		if ($user_id != $login_id) {
			if (Follows::model()->exists('user_id = :user_id AND follow_id = :follow_id', array('user_id'=>Yii::app()->user->id, 'follow_id'=>$user_id))) {
				$follow_status = 1;
			}
		}
		
		// Query user info
		$user_info = Yii::app()->db->createCommand()
		->select('u.id AS user_id, u.username, u.full_name, CONCAT(:path, u.avatar) AS avatar, u.location, u.website, u.bio, t.tweets_count, f1.following_count, f2.followers_count')
		->from('users AS u')
		->leftJoin('(SELECT user_id, COUNT(id) AS tweets_count FROM tweets WHERE user_id = :user_id) AS t', 't.user_id = u.id')
		->leftJoin('(SELECT user_id AS id, COUNT(follow_id) AS following_count FROM follows WHERE user_id = :user_id) AS f1', 'f1.id = u.id')
		->leftJoin('(SELECT follow_id AS id, COUNT(user_id) AS followers_count FROM follows WHERE follow_id = :user_id) AS f2', 'f2.id = u.id')
		->where('u.id = :user_id')
		->limit(1)
		->queryRow(true, array('user_id'=>$user_id, 'path'=>Yii::app()->createAbsoluteUrl('avatars').'/'));
		
		if (isset($user_info)) {
			$user_info['follow_status'] = $follow_status;
			$this->end($user_info);
		} else {
			$this->end(array('result'=>0));
		}
	}

	/**
	 * actionFollowing
	 * 
	 * Get list of following users
	 * 
	 * @param user_id:	If this param not passing,　the id of the authenticated user as default value.
	 * @param count:	max number of element will return.
	 * @param max_id:	(Optional) Return result with user id greater than max_id
	 * @param since_id:	(Optional) Return result with user id less than since_id
	 * 
	 * @return array of user info
	 */
	public function actionFollowing() {
		
		$login_id = Yii::app()->user->id;
		$user_id = Yii::app()->request->getParam('user_id');
		$count = Yii::app()->request->getParam('count', 20);
		$since_id = Yii::app()->request->getParam('since_id');
		$max_id = Yii::app()->request->getParam('max_id');
		
		$sql = Yii::app()->db->createCommand();
		
		if ($user_id && $user_id != $login_id) {
			$sql->select('f.id AS order_id, u.id AS user_id, u.username, u.full_name, CONCAT(:path,u.avatar) AS avatar, u.location, u.website, u.bio, f1.status');
			$sql->leftJoin('follows AS f1', 'f1.user_id = :login_id AND f1.follow_id = f.user_id', array('login_id'=>$login_id));
		} else {
			$user_id = $login_id;
			$sql->select('f.id AS order_id, u.id AS user_id, u.username, u.full_name, CONCAT(:path,u.avatar) AS avatar, u.location, u.website, u.bio, 1 AS status');
		}
		
		$sql->from('follows AS f');
		$sql->join('users as u', 'u.id = f.follow_id');
		$sql->limit($count);
		$sql->order('f.id DESC');
		
		if ($max_id && $since_id)
			$sql->where('f.id > :max_id AND f.id < :since_id AND f.user_id = :user_id', array('max_id'=>$max_id, 'since_id'=>$since_id));
		else if ($since_id)
			$sql->where('f.id < :since_id AND f.user_id = :user_id', array('since_id'=>$since_id));
		else if ($max_id)
			$sql->where('f.id > :max_id AND f.user_id = :user_id', array('max_id'=>$max_id));
		else
			$sql->where('f.user_id = :user_id');
		
		$following = $sql->queryAll(true, array('user_id'=>$user_id, 'path'=>Yii::app()->createAbsoluteUrl('avatars').'/'));
		$this->end($following);
	}

	/**
	 * actionFollowers
	 *
	 * Get list of follower users
	 *
	 * @param user_id:	If this param not passing,　the id of the authenticated user as default value.
	 * @param count:	max number of element will return.
	 * @param max_id:	(Optional) Return result with user id greater than max_id
	 * @param since_id:	(Optional) Return result with user id less than since_id
	 *
	 * @return array of user info
	 */
	public function actionFollowers() {
		
		$login_id = Yii::app()->user->id;
		$user_id = Yii::app()->request->getParam('user_id', $login_id);
		$count = (int)Yii::app()->request->getParam('count', 20);
		$since_id = Yii::app()->request->getParam('since_id');
		$max_id = Yii::app()->request->getParam('max_id');
		
		$sql = Yii::app()->db->createCommand();
		$sql->select('f.id AS order_id, u.id AS user_id, u.username, u.full_name, CONCAT(:path,u.avatar) AS avatar, u.location, u.website, u.bio, f1.status');
		$sql->from('follows AS f');
		$sql->join('users as u', 'u.id = f.user_id');
		$sql->leftJoin('follows AS f1', 'f1.user_id = :login_id AND f1.follow_id = f.user_id', array('login_id'=>$login_id));
		$sql->order('f.id DESC');
		$sql->limit($count);
		
		if ($max_id && $since_id) {
			$sql->where('f.id > :max_id AND f.id < :since_id AND f.follow_id = :user_id', array('max_id'=>$max_id, 'since_id'=>$since_id, 'user_id'=>$user_id));
		} else if ($since_id) {
			$sql->where('f.id < :since_id AND f.follow_id = :user_id', array('since_id'=>$since_id,'user_id'=>$user_id));
		} else if ($max_id) {
			$sql->where('f.id > :max_id AND f.follow_id = :user_id', array('max_id'=>$max_id, 'user_id'=>$user_id));
		} else {
			$sql->where('f.follow_id = :user_id', array('user_id'=>$user_id));
		}	
		
		$followers = $sql->queryAll(true, array('path'=>Yii::app()->createAbsoluteUrl('avatars').'/'));
		$this->end($followers);
	}

	/**
	 * actionFavorites
	 *
	 * Get list of favorite tweets
	 *
	 * @param user_id:	If this param not passing,　the id of the authenticated user as default value.
	 * @param count:	max number of element want to return.
	 * @param max_id:	(Optional) Return result with user id greater than max_id
	 * @param since_id:	(Optional) Return result with user id less than since_id
	 *
	 * @return array of favoried tweets
	 */
	public function actionFavorites()
	{
		$user_id = Yii::app()->request->getParam('user_id', Yii::app()->user->id);
		$count = Yii::app()->request->getParam('count', 20);
		$since_id = Yii::app()->request->getParam('since_id');
		$max_id = Yii::app()->request->getParam('max_id');

		$sql = Yii::app()->db->createCommand();
		$sql->select('t.id AS tweet_id, t.content, t.created_time, t.user_id, u.username, u.full_name, CONCAT(:path, u.avatar) AS avatar');
		$sql->from('favorites AS f');
		$sql->join('tweets AS t', 't.id = f.tweet_id AND f.user_id = :user_id');
		$sql->join('users AS u', 'u.id = t.user_id');
		$sql->order('t.id DESC');
		$sql->limit($count);

		if ($max_id)
			$sql->where('t.id > :max_id', array('max_id'=>$max_id));
		else if ($since_id)
			$sql->where('t.id < :since_id', array('since_id'=>$since_id));

		$favorites = $sql->queryAll(true, array('user_id'=>$user_id, 'path'=>Yii::app()->createAbsoluteUrl('avatars').'/'));
		$this->end($favorites);
	}
	
	/**
	 * actionFollow
	 *
	 * Make the authenticated user follow another user
	 *
	 * @param user_id:	id of user, who want to follow.
	 */
	public function actionFollow()
	{
		$follow_id = Yii::app()->request->getParam('follow_id');
		$user_id = Yii::app()->user->id;

		if ($user_id === $follow_id)
			$this->end(array('result'=>-1));

		$followed = Yii::app()->db->createCommand()
		->select('f.id')
		->from('follows AS f')
		->where('f.user_id = :user_id AND f.follow_id = :follow_id')
		->queryAll(true, array('user_id' => $user_id, 'follow_id' => $follow_id));
		 
		if ($followed) {
			$this->end(array('result'=>-2));
			 
		} else {
			$follow = new Follows();
			$follow->user_id = $user_id;
			$follow->follow_id = $follow_id;
			$follow->status = Follows::NOMAL;
			$follow->time = new CDbExpression("NOW()");

			if ($follow->save()) {
				$sql = "INSERT INTO timeline (user_id, tweet_id) SELECT $user_id, t.id FROM tweets AS t WHERE t.user_id =:follow_id LIMIT 50";
				Yii::app()->db->createCommand($sql)->execute(array('follow_id'=>$follow_id));
				$this->end(array('result'=>1));
			}
			else
				$this->end(array('result'=>0));
		}
	}

	/**
	 * actionUnfollow
	 *
	 * Make the authenticated user unfollow another user, who is followed user
	 *
	 * @param user_id:	id of user, who want to unfollow.
	 */
	public function actionUnfollow()
	{
		$follow_id = Yii::app()->request->getParam('follow_id');
		$user_id = Yii::app()->user->id;

		$followed = Follows::model()->find('t.user_id = :user_id AND t.follow_id = :follow_id', array('user_id' => $user_id, 'follow_id' => $follow_id));

		if ($followed) {
			if ($followed->delete()) {
				$sql = "DELETE FROM timeline WHERE EXISTS (SELECT $user_id, t.id FROM tweets AS t WHERE t.user_id = :follow_id)";
				Yii::app()->db->createCommand($sql)->execute(array('follow_id'=>$follow_id));
				$this->end(array('result'=>1));
			}
			else
				$this->end(array('result'=>0));
		} else {
			$this->end(array('result'=>0));
		}
	}

	/**
	 * actionUpdateProfile
	 * 
	 * Update user profile
	 * 
	 * @param full_name:	fullname of the authenticated user
	 * @param bio:	biography of the authenticated user
	 * @param website: website of the authenticated user
	 * @param location: location of the authenticated user
	 */
	public function actionUpdateProfile() {
		$full_name = Yii::app()->request->getParam('full_name');
		$bio = Yii::app()->request->getParam('bio');
		$website = Yii::app()->request->getParam('website');
		$location = Yii::app()->request->getParam('location');
		 
		$user = Users::model()->findByPk(Yii::app()->user->id);
		$user->full_name = $full_name;
		$user->bio = $bio;
		$user->website = $website;
		$user->location = $location;

		if ($user->save())
			$this->end(array('result'=>1));
		else {
			$this->end(array('result'=>0));
		}
	}

	/**
	 * actionUpdateAvatar
	 * 
	 * Update user avatar
	 * 
	 * @param avatar base64 encode of image file.
	 */
	public function actionUpdateAvatar() {
		$encode_avatar = Yii::app()->request->getParam('avatar');
		 
		if ($encode_avatar) {
			$user = Users::model()->findByPk(Yii::app()->user->id);
			$file_pah = Yii::getPathOfAlias('webroot').'/avatars/';
			$file_name = $user->username.'php';
			$avatar = base64_decode($encode_avatar);

			$file = fopen($file_pah.$file_name, 'wb+');
			fwrite($file, $avatar);
			fclose($file);

			$this->end(array('result'=>1));
		}

		$this->end(array('result'=>0));
	}

	/**
	 * actionSuggestion
	 * 
	 * Suggest user by username or fullname
	 * 
	 * @param slug:
	 * @param max_id:	(Optional) Return result with user id greater than max_id
	 * @param since_id:	(Optional) Return result with user id less than since_id
	 */
	 public function actionSuggestion() {
		$slug = Yii::app()->request->getParam('slug');
		$count = Yii::app()->request->getParam('count', 20);
		$since_id = Yii::app()->request->getParam('since_id');
		$max_id = Yii::app()->request->getParam('max_id');
			
		if ($slug)
		{
			$slug = '%'.$slug.'%';
			
			$command = Yii::app()->db->createCommand();
			$command->select('DISTINCT(u.id) AS user_id, u.username, u.full_name, CONCAT(:path,u.avatar) AS avatar');
			$command->from('follows AS f');
			$command->join('users AS u', 'u.id = f.follow_id OR u.id = f.user_id');
			
			if ($since_id && $max_id)
				$command->where('(f.user_id = :user_id OR f.follow_id = :user_id) AND u.id < :since_id AND u.id > :max_id AND (u.username LIKE :slug OR u.full_name LIKE :slug)', array('since_id'=>$since_id, 'max_id'=>$max_id));
			if ($since_id)
				$command->where('(f.user_id = :user_id OR f.follow_id = :user_id) AND u.id < :since_id AND (u.username LIKE :slug OR u.full_name LIKE :slug)', array('since_id'=>$since_id));
			else if ($max_id)
				$command->where('(f.user_id = :user_id OR f.follow_id = :user_id) AND u.id > :max_id AND (u.username LIKE :slug OR u.full_name LIKE :slug)', array('max_id'=>$max_id));
			else
				$command->where('(f.user_id = :user_id OR f.follow_id = :user_id) AND (u.username LIKE :slug OR u.full_name LIKE :slug)');
				
			$command->limit($count);
			$suggestion = $command->queryAll(true, array('path'=>Yii::app()->createAbsoluteUrl('avatars').'/','slug'=>$slug, 'user_id'=>Yii::app()->user->id));
				
			if ($suggestion)
				$this->end($suggestion);
			else
				$this->end(array('result'=>0));
		}
	}
	
	public function actionSearch() {
		$slug = Yii::app()->request->getParam('slug');
		$count = Yii::app()->request->getParam('count', 20);
		$since_id = Yii::app()->request->getParam('since_id');
		$max_id = Yii::app()->request->getParam('max_id');
		
		if ($slug) {
			$slug = '%'.$slug.'%';
			
			$command = Yii::app()->db->createCommand();
			$command->select('u.id AS user_id, u.username, u.full_name, CONCAT(:path,u.avatar) AS avatar');
			$command->from('users AS u');
				
			if ($since_id) {
				$command->where('u.id < :since_id AND (u.username LIKE :slug OR u.full_name LIKE :slug)', array('since_id'=>$since_id));
			} else if ($max_id) {
				$command->where('u.id > :max_id AND (u.username LIKE :slug OR u.full_name LIKE :slug)', array('max_id'=>$max_id));
			} else {
				$command->where('u.username LIKE :slug OR u.full_name LIKE :slug');
			}
				
			$command->limit($count);
			$result = $command->queryAll(true, array('path'=>Yii::app()->createAbsoluteUrl('avatars').'/','slug'=>$slug));
				
			if ($result)
				$this->end($result);
			else
				$this->end(array('result'=>0));
		}
	}

	public function filters() {
		return array(
				'accessControl',
		);
	}

	public function accessRules() {
		return array(
				array('allow', // allow authenticated users to access all actions„ÄÄ„ÄÄÔºà„ÄÄ„Åï„Çå„Åü„É¶„Éº„Ç∂„Éº„ÅØ„Åô„Åπ„Å¶„ÅÆ„Ç¢„ÇØ„Ç∑„Éß„É≥„Å∏„ÅÆ„Ç¢„ÇØ„Çª„Çπ„ÇíË®±ÂèØ„Åô„Çã„ÄÄÔºâ
						'users' => array('@'),
				),
				array('deny', // deny all users„ÄÄ(„Åô„Åπ„Å¶„ÅÆ„É¶„Éº„Ç∂„Éº„ÇíÊãíÂê¶„Åô„Çã„ÄÇ)
						'users' => array('*'),
				),
		);
	}
}